package com.walterweimod.auxiliary_attributes.mobeffect;

import com.google.common.collect.*;
import com.walterweimod.auxiliary_attributes.attribute.ModAttributes;
import com.walterweimod.auxiliary_attributes.util.ModAttributeUtils;
import net.minecraft.client.resources.sounds.Sound;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.util.Mth;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectCategory;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.attributes.*;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.food.FoodData;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraftforge.registries.ForgeRegistries;
import org.apache.commons.lang3.RandomUtils;
import org.jetbrains.annotations.NotNull;

import java.util.*;

import static com.walterweimod.auxiliary_attributes.util.ModMobEffectUtils.*;
import static com.walterweimod.auxiliary_attributes.util.ModLivingEntityUtils.*;
import static com.walterweimod.auxiliary_attributes.util.ModAttributeUtils.*;
import static com.walterweimod.auxiliary_attributes.Auxiliary_attributes.*;

public class KingsBlessing extends MobEffect {
    private static final UUID CRITICAL_HIT_CHANCE_UUID = getNameAttributeUUID(
            ModAttributes.CRITICAL_HIT_CHANCE.get(),
            "kings_blessing"
    );

    private static final UUID CRITICAL_HIT_DAMAGE_UUID = getNameAttributeUUID(
            ModAttributes.CRITICAL_HIT_DAMAGE.get(),
            "kings_blessing"
    );

    private static final UUID MAX_HEALTH_UUID = getNameAttributeUUID(
            Attributes.MAX_HEALTH,
            "kings_blessing"
    );

    protected KingsBlessing() {
        super(MobEffectCategory.BENEFICIAL, 16766720);
    }

    @Override
    public @NotNull Component getDisplayName() {
        return new TextComponent("King's Blessing");
    }

    @Override
    public void addAttributeModifiers(@NotNull LivingEntity p_19478_,
                                      @NotNull AttributeMap p_19479_,
                                      int p_19480_) {
        addAbsorptionAmount(p_19478_, 20.0F + 10.0F * p_19480_);

        ModAttributeUtils.addAttributeModifier(
                p_19478_,
                ModAttributes.CRITICAL_HIT_CHANCE.get(),
                60.0D + 30.0 * p_19480_,
                CRITICAL_HIT_CHANCE_UUID,
                AttributeModifier.Operation.ADDITION,
                false
        );

        ModAttributeUtils.addAttributeModifier(
                p_19478_,
                ModAttributes.CRITICAL_HIT_DAMAGE.get(),
                15.0D + 10.0 * p_19480_,
                CRITICAL_HIT_DAMAGE_UUID,
                AttributeModifier.Operation.ADDITION,
                false
        );

        ModAttributeUtils.addAttributeModifier(
                p_19478_,
                Attributes.MAX_HEALTH,
                20.0D + 10.0 * p_19480_,
                MAX_HEALTH_UUID,
                AttributeModifier.Operation.ADDITION,
                false
        );

        p_19478_.heal((0.2F + 0.1F * p_19480_) * p_19478_.getMaxHealth());

        if (p_19478_ instanceof Player player){
            FoodData foodData = player.getFoodData();

            foodData.setExhaustion(-20.0F - 10.0F * p_19480_);
            foodData.setFoodLevel(20 + 10 * p_19480_);
            foodData.setSaturation(20 + 10 * p_19480_);
        }

        super.addAttributeModifiers(p_19478_, p_19479_, p_19480_);
    }

    @Override
    public void removeAttributeModifiers(@NotNull LivingEntity p_19469_,
                                         @NotNull AttributeMap p_19470_,
                                         int p_19471_) {
        addAbsorptionAmount(p_19469_, 20.0F + 10.0F * p_19471_);

        ModAttributeUtils.removeAttributeModifiers(
                p_19469_,
                ImmutableMultimap.of(
                        ModAttributes.CRITICAL_HIT_CHANCE.get(), CRITICAL_HIT_CHANCE_UUID,
                        ModAttributes.CRITICAL_HIT_DAMAGE.get(), CRITICAL_HIT_DAMAGE_UUID,
                        Attributes.MAX_HEALTH, MAX_HEALTH_UUID
                )
        );
    }

    @Override
    public boolean isDurationEffectTick(int p_19455_, int p_19456_) {
        int interval = Mth.clamp((int) (80 * Math.pow(1.5D, -p_19456_)), 10, 80);

        return p_19455_ % interval == 0;
    }

    @Override
    public void applyEffectTick(@NotNull LivingEntity p_19467_, int p_19468_) {
        if (!p_19467_.level.isClientSide()){ // must on server side
            Collection<MobEffect> mobEffects = ForgeRegistries.MOB_EFFECTS.getValues();
            ArrayList<MobEffect> myMobEffects = Lists.newArrayList();

            mobEffects.forEach(mobEffect -> {
                if (mobEffect.isBeneficial()
                        && !mobEffect.isInstantenous()
                        && mobEffect != this){
                    myMobEffects.add(mobEffect);
                }
            });

            Collections.shuffle(myMobEffects);

            int max_duration = 600 * (int) Math.ceil(Math.pow(1.5D, Math.min(p_19468_, 34)));

            for (int i = 0; i < Math.min(myMobEffects.size(), 2); i++) {
                MobEffect mobEffect = myMobEffects.get(i);

                addEffect(
                        p_19467_,
                        mobEffect,
                        RandomUtils.nextInt(max_duration / 5, max_duration),
                        Math.min(RandomUtils.nextInt(0, p_19468_ + + 1), getMaxMobEffectAmplifier(mobEffect))
                );
            }

            removeHarmfulMobEffects(p_19467_);

            if (p_19467_ instanceof Player){
                Player player = (Player) p_19467_;

                player.giveExperiencePoints(2 + p_19468_);

                if (player.getInventory().getFreeSlot() != -1){
                    player.addItem(new ItemStack(Items.EMERALD, 2 + p_19468_));
                }
            }
        }
    }
}
